package main;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * @author Caitlin Leksana and Matt Berntein
 * MatLin Inc. 
 */
public class QNote extends JFrame implements KeyListener{

	private final Dimension SIZE = new Dimension(800,800);

	private JTextField input = new JTextField();
	private JTabbedPane display = new JTabbedPane();
	private JButton interpret = new JButton("Go");
	private Menu menu = new Menu(this);
	private ArrayList<Score> scores = new ArrayList<Score>();
	private int currentTab = -1;
	private Score currentScore = null;
	private boolean meta = false;
	private static BufferedImage icon;
	private static JFrame load;

	public static void main(String[] args) {
		try{
			icon = ImageIO.read(new File("QnoteIcon.png"));
		}catch(IOException e){}
		load = showLoadingScreen();
		new QNote();
	}


	/**
	 * Initializes the main GUI. 
	 * This also calls all the interpretation code in the Score class
	 */
	public QNote(){
		super("QNote Composer");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setLayout(new BorderLayout());
		setIconImage(icon);
		display.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent arg0) {
				currentScore = (Score) display.getSelectedComponent();
			}
		});


		interpret.addActionListener(new ActionListener() {
			//sets the current score to the active tab
			public void actionPerformed(ActionEvent arg0) {
				if(currentScore != null){
					String text = input.getText();
					if(text.equals(""))
						JOptionPane.showMessageDialog(QNote.this, "Error: Please enter text", "No Text", JOptionPane.ERROR_MESSAGE);
					else{
						currentScore.interpret(text);
						input.setText("");

					}
				}
				else{
					JOptionPane.showMessageDialog(QNote.this, "Error: Create a Score first\nFile > New", "No Score", JOptionPane.ERROR_MESSAGE);
				}

			}
		});

		JPanel south = new JPanel();
		BoxLayout southLayout = new BoxLayout(south, BoxLayout.LINE_AXIS);
		south.setLayout(southLayout);
		south.add(input);
		south.add(Box.createHorizontalStrut(5));
		south.add(interpret);
		add(display, BorderLayout.CENTER);
		add(south, BorderLayout.SOUTH);
		add(menu, BorderLayout.NORTH);
		input.addKeyListener(this);
		interpret.getRootPane().setDefaultButton(interpret);
		setSize(SIZE);
		try{Thread.sleep(2000);}catch(InterruptedException e){}
		load.dispose();
		setVisible(true);
	}


	private static JFrame showLoadingScreen() {
		return new LoadingScreen(icon);
	}


	/**
	 * creates a new score
	 * @param name Score name
	 * @param d Dimensions of the score
	 * @param ctype clef
	 * @param key key
	 * @param maj Major or minor
	 * @param time time signature
	 */
	public void newScore(String name, Dimension d, String ctype, String key, Boolean maj, TimeSignature time){		
		currentTab++;
		Score temp = new Score(name, display.getSize(), ctype, key, maj, time);
		scores.add(temp);
		int scoresInd = scores.size()-1;
		display.insertTab(name, null, scores.get(scoresInd), name, currentTab);
		display.setSelectedIndex(currentTab);
		currentScore = temp;

	}

	/**
	 * Given a score code string, turns it into a score object
	 * @param code The score code
	 */
	public void interpret(String code){
		String name = pullInfo(code);
		code = code.substring(code.indexOf('\n')+1);
		String clef = pullInfo(code);
		code = code.substring(code.indexOf('\n')+1);
		String key = pullInfo(code);
		boolean maj = key.contains("Major")? true:false;
		key = key.substring(0, key.indexOf(' '));
		code = code.substring(code.indexOf('\n')+1);
		String time = pullInfo(code);
		TimeSignature ts = new TimeSignature(time);
		code = code.substring(code.indexOf('\n')+1);//removes extra line
		code = code.trim();

		newScore(name, display.getSize(), clef, key, maj, ts);

		currentScore.interpret(code);

	}

	/**
	 * Private, pulls info from the header of score 
	 * @param s line of the header
	 * @return info 
	 */
	private String pullInfo(String s){
		String line = s.substring(0, s.indexOf('\n'));
		return line.substring(line.indexOf(' ')).trim();
	}

	@Override
	public void keyPressed(KeyEvent e) {
		if(e.getKeyCode() == KeyEvent.VK_META){
			meta = true;
		}
		if(e.getKeyCode() == KeyEvent.VK_N)
			if(meta)
				new NewScoreScreen(this);
		if(e.getKeyCode() == KeyEvent.VK_H)
			if(meta)
				menu.callHelpScreen();
		if(e.getKeyCode() == KeyEvent.VK_S)
			if(meta)
				menu.saveFile();
		if(e.getKeyCode() == KeyEvent.VK_O)
			if(meta)
				menu.openFile();
		if(e.getKeyCode() == KeyEvent.VK_W)
			if(meta)
				menu.showScoreCode();
	}

	@Override
	public void keyReleased(KeyEvent e) {
		if(e.getKeyCode() == KeyEvent.VK_META)
			meta = false;

	}

	@Override
	public void keyTyped(KeyEvent e) {
	}

	/**
	 * 
	 * @return current score
	 */
	public Score getCurrentScore()
	{
		return currentScore;
	}

	/**
	 * 
	 * @return the list of scores
	 */
	public ArrayList<Score> getScores(){
		return scores;
	}

	/**
	 * removes a score given an index
	 * @param index index of score to be removed
	 */
	public void removeScore(int index){
		scores.remove(index);
		display.remove(index);
		currentTab--;

	}

	/**
	 * Removes a given score
	 * @param s score to be removed
	 */
	public void removeScore(Score s){
		scores.remove(s);
		display.remove(s);
		currentTab--;
	}

	/**
	 * Shows an error message
	 */
	public void showErrorMessage(){
		JOptionPane.showMessageDialog(QNote.this, "Error: Create a Score first\nFile > New", "No Score", JOptionPane.ERROR_MESSAGE);
	}
}

